using System;
using System.Collections.Generic;
using System.Text;
using GarageGames.Torque.GUI;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Xyne.Regions;
using GarageGames.Torque.T2D;
using GarageGames.Torque.Sim;
using Microsoft.Xna.Framework.Input;
using GarageGames.Torque.GameUtil;
using GarageGames.Torque.Core;
using GarageGames.Torque.Platform;
using GarageGames.Torque.GFX;
using System.Collections;
using Xyne.Utilities;
using Xyne.Templates.PuzzlePieceTemplate;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.GamerServices;
using GarageGames.Torque.XNA;
using GarageGames.Torque.Materials;
using Xyne.Objects.Common;
using System.Threading;
using Xyne.Templates;
using Xyne.Network;
using Xyne.Events;
using Xyne.GUI.GUIControls;
using Xyne.GUI.GUIControls.Menu;

namespace Xyne.GUI
{
    class MainMenuGUI : GUISceneview, IGUIScreen
    {
        #region members
        private Vector2 textPositionModifier;

        private AvailableNetworkSessionCollection _availableSelections;


        #region FOR TESTING
        private GUIText titleObject;
        private GUIText ControlsObject;
        private GUIText statusObject;
        #endregion

        #region Menus
        CircleMenu _joinMenu;
        CircleMenu _lobby;
        CircleMenu _deckMenu;
        #endregion



        private bool ready = false;

        private int whatNUMBER;

        private MenuManager _mainMenuManager;
        #endregion

        #region Properties
        public Vector2 TextPositionModifier
        {
            get
            {
                return textPositionModifier;
            }
        }
        #endregion

        #region Constructor
        public MainMenuGUI()
        {
            GUIStyle stylePlayGUI = new GUIStyle();
            whatNUMBER = 0;
            Name = "MainMenu";
            Style = stylePlayGUI;
            Size = Game.Instance.ClientBounds;

            OnGUIWake = new OnWakeDelegate(StartMainGUI);
        }
        #endregion

        #region Public Methods
        public void StartMainGUI(GUIControl control)
        {
            Game.Instance.Window.Title = "Xyne";


            bool wideScreen = GFXDevice.IsWideScreen((int)Game.Instance.ClientBounds.X, (int)Game.Instance.ClientBounds.Y);
            if (Game.Network != null && Game.Network.Session != null && !Game.Network.Session.IsDisposed)
            {
                Game.Network.Session.Dispose();
            }
            InitializeUI(wideScreen);
        }
        #endregion

        private void InitializeUI(bool isWideScreen)
        {
            Game.Instance.SceneLoader.Load(@"data\scenes\default.txscene");
            EventManager.Instance.Callbacks.Add(new EventManager.EventReceivedDelegate(EventReceived));

            T2DSceneCamera camera = TorqueObjectDatabase.Instance.FindObject<T2DSceneCamera>();

            if (isWideScreen)
            {
                camera.Extent = new Vector2(1024, 576);
                camera.CenterPosition = new Vector2(512, 288);

                textPositionModifier = new Vector2(1199f / 1024f, 671f / 576f);
            }
            else
            {
                textPositionModifier = new Vector2(1, 1);
            }
            //camera.CenterPosition + new Vector2(100.0f, 50.0f)
            _availableSelections = null;
            CreateMenus();

            #region FOR TESTING
            GUITextStyle textStyle = new GUITextStyle();
            textStyle.SizeToText = true;
            textStyle.FontType = "arial12";
            textStyle.PreserveAspectRatio = false;
            textStyle.TextColor[CustomColor.ColorBase] = Color.White;
            textStyle.Alignment = TextAlignment.JustifyLeft;
            titleObject = new GUIText();
            titleObject.Text = "Multiplayer";
            titleObject.Position = new Vector2(64, 64);
            titleObject.Size = new Vector2(512, 64);
            titleObject.Style = textStyle;
            titleObject.Visible = true;
            titleObject.Folder = this;
  /*          ControlsObject = new GUIText();
            ControlsObject.Text = "A Host Session, Y Join Session, X Debug, B Quit";
            ControlsObject.Position = new Vector2(64, 128);
            ControlsObject.Size = new Vector2(512, 64);
            ControlsObject.Style = textStyle;
            ControlsObject.Visible = true;
            ControlsObject.Folder = this;*/
            statusObject = new GUIText();
            statusObject.Text = "";
            statusObject.Position = new Vector2(64, 256);
            statusObject.Size = new Vector2(512, 64);
            statusObject.Style = textStyle;
            statusObject.Visible = true;
            statusObject.Folder = this;

            if (whatNUMBER == 0)
            {
                T2DStaticSprite background = new T2DStaticSprite();
                background.Size = Bounds.Extent;
                background.Position = Bounds.Center;
                background.Layer = Game.BackgroundLayer;
                SimpleMaterial material = new SimpleMaterial();
                material.TextureFilename = @"data\images\ui\controller\xboxControllerRightThumbstick.tga";
                background.Material = material;

          //      bool tempbool = TorqueObjectDatabase.Instance.Register(background);
            }
            else
            {
                T2DStaticSprite background = new T2DStaticSprite();
                background.Size = Bounds.Extent;
                background.Position = Bounds.Center;
                background.Layer = Game.BackgroundLayer;
                SimpleMaterial material = new SimpleMaterial();
                material.TextureFilename = @"data\images\grey.png";
                background.Material = material;

       //         bool tempbool = TorqueObjectDatabase.Instance.Register(background);
            }
            whatNUMBER++;
            #endregion

            // Check to see if gamer 0 is logged on
            if (!IsFirstPlayerSignedIn())
            {
                statusObject.Text = "Signing in to LIVE";

                if (!Guide.IsVisible)
                {
                    SignedInGamer.SignedIn += new EventHandler<SignedInEventArgs>(SignedIn);
                    Guide.ShowSignIn(1, false);
                }
            }
            else
            {
                statusObject.Text = "Already signed in, good job!";
                if (!UserSaveDataManager.Instance.Loaded)
                {
                    UserSaveDataManager.Instance.LoadUserSaveData();
                }
            }
        }

        private void CreateMenus()
        {
            CircleMenu rootMenu = new CircleMenu(0,150.0f, "Main Menu");
    //        _mainMenuManager = new MenuManager(Bounds.Center, new Vector2(100, Bounds.Height - 300), rootMenu);
            _mainMenuManager = new MenuManager(Bounds.Center, new Vector2(100, Bounds.Height - 300));
            _mainMenuManager.CompletelyBackedOut = new MenuManager.CompletelyBackedOutDelegate(Quit);
            _lobby = new CircleMenu(0,150.0f, "Host a game");
            _lobby.Manager = _mainMenuManager;
            _lobby.MenuItemSelected = new MenuItem.MenuItemSelectedDelegate(OnMenuSelectHost);
            _lobby.MenuCancelled = new CircleMenu.MenuCanceledDelegate(LobbyCancelled);
            rootMenu.AddItem(_lobby);

            _joinMenu = new CircleMenu(1,150.0f, "Join Menu");
            _joinMenu.MenuItemSelected = new MenuItem.MenuItemSelectedDelegate(OnMenuSelectSearch);
           // _joinMenu.MenuShown = new CircleMenu.MenuShownDelegate(SearchForSessions);
            _joinMenu.Manager = _mainMenuManager;
            _joinMenu.MenuCancelled = new CircleMenu.MenuCanceledDelegate(SearchForSessionsCancelled);
            MenuItem refreshMenuItem = new SessionMenuItem(8, "Refresh");
            refreshMenuItem.MenuItemSelected = new MenuItem.MenuItemSelectedDelegate(SearchForSessions);
            _joinMenu.AddItem(refreshMenuItem);

            rootMenu.AddItem(_joinMenu);

            MenuItem debugMenuItem = new MenuItem("Debug");
            debugMenuItem.MenuItemSelected = new MenuItem.MenuItemSelectedDelegate(OnMenuSelectDebug);

            rootMenu.AddItem(debugMenuItem);
            MenuItem quitItem = new MenuItem("Quit");
            quitItem.MenuItemSelected = new MenuItem.MenuItemSelectedDelegate(OnMenuSelectQuit);
            rootMenu.AddItem(quitItem);


            _mainMenuManager.Current = rootMenu;
        }

        private void Quit()
        {
            if (Game.Network != null)
            {
                //Game.Network.CloseSession();
                Game.Network.Dispose();
            }

            Game.Instance.Exit();
        }

        private void SearchForSessions()
        {
            if ((Game.Network == null || Game.Network.Session == null || Game.Network.Session.IsDisposed) && IsFirstPlayerSignedIn())
            {
                ClientComponent client = new ClientComponent(Game.Instance);
                Game.Network = client;
                _joinMenu.Clear();
                _availableSelections = null;
                client.SearchForSessions(SessionsFound);
                statusObject.Text = "Finding sessions...";
            }
        }

        private void SearchForSessionsCancelled()
        {

        }

        private void LobbyCancelled()
        {
            if (Game.Network.Session != null && !Game.Network.Session.IsDisposed)
            {
                Game.Network.Session.Dispose();
            }
        }

        private void HostGame()
        {
            if ((Game.Network == null || Game.Network.Session.IsDisposed) && IsFirstPlayerSignedIn())
            {
                ServerComponent server = new ServerComponent(Game.Instance);
                Game.Network = server;
                _lobby.Clear();
                SessionMenuItem leaveLobbyItem = new SessionMenuItem(0, "Leave Lobby");
                leaveLobbyItem.MenuItemSelected = new MenuItem.MenuItemSelectedDelegate(LeaveLobby);
                _lobby.AddItem(leaveLobbyItem);
                _lobby.AddItem(GetDeckMenu());
                server.CreateLobby();
                Game.Network.Session.GamerJoined += new EventHandler<GamerJoinedEventArgs>(GamerJoined);
                Game.Network.Session.GameStarted += new EventHandler<GameStartedEventArgs>(GameStarted);

                statusObject.Text = "Session state = " + Game.Network.Session.SessionState + ", waiting...";
            }
        }

        private CircleMenu GetDeckMenu()
        {

            _deckMenu = new CircleMenu(1, 100.0f, "Change Menu\nCurrent Menu:"+UserSaveDataManager.Instance.UserSaveData.UserDeck.Name+" Deck");
            _deckMenu.Size = new Vector2(200, 100);
            _deckMenu.Manager = _mainMenuManager;

            SessionMenuItem fireDeckMenuItem = new SessionMenuItem(0, "Fire Deck");
            fireDeckMenuItem.MenuItemSelected = new MenuItem.MenuItemSelectedDelegate(OnDeckSelected);

            SessionMenuItem waterDeckMenuItem = new SessionMenuItem(1, "Water Deck");
            waterDeckMenuItem.MenuItemSelected = new MenuItem.MenuItemSelectedDelegate(OnDeckSelected);

            _deckMenu.AddItem(fireDeckMenuItem);
            _deckMenu.AddItem(waterDeckMenuItem);
            

            return _deckMenu;
        }

        private void StartDebug()
        {
            Game.Network = new DebugComponent(Game.Instance);
            CanvasStateMachine.Instance.NextCanvasState = CanvasStateMachine.CanvasStates.MainGame;
        }

        void SignedIn(object sender, SignedInEventArgs e)
        {
            if (IsFirstPlayerSignedIn())
            {
                statusObject.Text = "Signed in to LIVE";
                UserSaveDataManager.Instance.LoadUserSaveData();
            }
        }

        private bool IsFirstPlayerSignedIn()
        {
            foreach (SignedInGamer gamer in SignedInGamer.SignedInGamers)
            {
                if (gamer.PlayerIndex == PlayerIndex.One)
                    return true;
            }

            return false;
        }

        private void JoinedLobby(MenuItem menuItem)
        {            
            ClientComponent client = Game.Network as ClientComponent;
            client.JoinSession(client.AvailableSessions[menuItem.MenuID]);
            client.AvailableSessions.Dispose();
            Game.Network.Session.GameStarted += new EventHandler<GameStartedEventArgs>(GameStarted);
            _lobby.Clear();
            Game.Network.Session.GamerLeft += new EventHandler<GamerLeftEventArgs>(GamerLeft);
            _lobby.AddItem(new SessionMenuItem(0, Game.Network.Gamer.Gamertag));
            _lobby.AddItem(GetDeckMenu());
            _lobby.AddItem(new SessionMenuItem(2, Game.Network.Session.Host.Gamertag));
            SessionMenuItem leaveLobbyItem = new SessionMenuItem(2, "Leave Lobby");
            leaveLobbyItem.MenuItemSelected = new MenuItem.MenuItemSelectedDelegate(LeaveLobby);
            _lobby.AddItem(leaveLobbyItem);
            _lobby.Selected();
        }

        #region Events

        private void OnMenuSelectQuit(MenuItem menuItem)
        {
            Quit();
        }

        private void OnMenuSelectDebug(MenuItem menuItem)
        {
            StartDebug();
        }

        private void OnMenuSelectSearch(MenuItem menuItem)
        {
            SearchForSessions();
        }

        private void OnMenuSelectHost(MenuItem menuItem)
        {
            HostGame();
        }

        private void OnMenuSelectStartGame(MenuItem menuItem)
        {
            Game.Network.Session.StartGame();
        }

        private void SearchForSessions(MenuItem sender)
        {
            SearchForSessions();
        }

        private void SessionsFound()
        {

            if (Game.Network != null && Game.Network is ClientComponent && Game.Network.Session == null)
            {
                ClientComponent client = Game.Network as ClientComponent;


                // Automatically join the first session for now
                if (client.AvailableSessions.Count > 0)
                {
                    for (int i = 0; i < 7; i++)
                    {
                        if (i < client.AvailableSessions.Count)
                        {
                            SessionMenuItem newSession = new SessionMenuItem(i, client.AvailableSessions[i].HostGamertag);
                            newSession.MenuItemSelected = new MenuItem.MenuItemSelectedDelegate(JoinedLobby);
                            _joinMenu.AddItem(newSession);
                        }
                        else
                        {
                            _joinMenu.AddItem(new SessionMenuItem(i, "Empty"));
                        }

                    }
                    statusObject.Text = "Found! Select a player...";
                }
                else
                {
                    statusObject.Text = "No available sessions, try again!";
                }
                SessionMenuItem refreshMenuItem = new SessionMenuItem(8, "Refresh");
                refreshMenuItem.MenuItemSelected = new MenuItem.MenuItemSelectedDelegate(SearchForSessions);
                _joinMenu.AddItem(refreshMenuItem);
            }
        }

        private void GameStarted(object sender, GameStartedEventArgs e)
        {
            // Start the game! :D
            CanvasStateMachine.Instance.NextCanvasState = CanvasStateMachine.CanvasStates.MainGame;
        }

        private void GamerJoined(object sender, GamerJoinedEventArgs e)
        {

            if (Game.Network.Session != null && Game.Network.Session.IsHost && Game.Network.Session.AllGamers.Count > 1)
            {

//                Game.Network.Session.StartGame();
                _lobby.AddItem(new SessionMenuItem(2, Game.Network.Gamer.Gamertag));
                _lobby.AddItem(new SessionMenuItem(3, e.Gamer.Gamertag));

                SessionMenuItem startGameItem = new SessionMenuItem(3, "Start Game");
                startGameItem.MenuItemSelected = new MenuItem.MenuItemSelectedDelegate(OnMenuSelectStartGame);
                _lobby.AddItem(startGameItem);


                Game.Network.Session.GamerLeft += new EventHandler<GamerLeftEventArgs>(GamerLeft);
                statusObject.Text = "";
            }
        }

        private void GamerLeft(object sender, GamerLeftEventArgs e)
        {
            LeaveLobby(null);           
        }

        private void LeaveLobby(MenuItem menuItem)
        {
            if (Game.Network.Session != null)
            {
                Game.Network.Session.Dispose();
                Game.Network.Session = null;
                _lobby.MenuCancel();
            }
        }


        private void EventReceived(Event e)
        {
        }

        public override void OnRender(Vector2 offset, GarageGames.Torque.MathUtil.RectangleF updateRect)
        {
            base.OnRender(offset, updateRect);
            _mainMenuManager.RefreshMenus();
        }

        private void OnDeckSelected(MenuItem menuItem)
        {
            if (menuItem.MenuID == 0)
            {
                _deckMenu.MenuName = "Change Menu\nCurrent Menu:Fire Deck";
                UserSaveDataManager.Instance.UserSaveData.UserDeck = DeckManager.GetDeck("Fire");

                UserSaveDataManager.Instance.SaveUserSaveData();
            }
            else
            {
                _deckMenu.MenuName = "Change Menu\nCurrent Menu:Water Deck";
                UserSaveDataManager.Instance.UserSaveData.UserDeck = DeckManager.GetDeck("Water");
                UserSaveDataManager.Instance.SaveUserSaveData();
            }

            _deckMenu.MenuCancel();
        }
        #endregion
    }
}
